package lexico;

import java.util.ArrayList;
import java.util.List;

/**
 * @author heekinho
 */
public class SymbolTable extends ArrayList<Token> {
    private int current = 0;

//    private static SymbolTable instance = new SymbolTable();

    public SymbolTable() {
    }


//    public static SymbolTable instance(){
//        return instance;
//    }

    public void pushBackToken(Token token){
            this.add(token);
    }

    /**
     * Talvez a responsabilidade de tratamento dos tokens seja dentro da classe
     * e não fora. Algo como o currentToken e getNextToken. Porém este efeito
     * pode ser conseguido facilmente pela iteração da Estrutura de dados fora
     * daqui.
     * @return
     */
//	public ArrayList<Token> getTokens(){
//		return tokens;
//	}


    /**
     * Imprime a lista de tokens
     */
    public void printTokens(){
		System.out.println("Tokens: ");
		for (Token token : this) System.out.println(token);
    }

	public void printTokensFromCurrent(){
		if(current >= size()) return;
		System.out.println("Tokens restantes: ");
		for(int i = current; i < size(); i++) System.out.println(get(i));
	}

	public List<Token> getRemainingTokens(){
		return new ArrayList<Token>(this.subList(current, size()));
	}

    /**
     * Obtendo o token atual
     * @return o token atual
     */
    public Token getCurrent(){
        return this.get(current);
    }

    /**
     * Consome o token atual
     * @return o token atual
     */
    public Token consumeCurrent(){
        return this.get(current++);
    }

	/**
	 * Consome o token, e retorna o mais novo getCurrent.
	 * Equivale a:
	 * st.consumeCurrent();
	 * st.getCurrent();
	 * @return o "próximo" token (que virou o current).
	 */
	public Token getNext(){
		++current;
		if(!eof()) return this.get(current);
		else return new Token(TokenClass.UNDEFINED, "EOF", -1, -1);
	}


    public boolean eof(){
        if(this.size() == current) return true;
        return false;
    }


    public void reset(){
        this.current = 0;
    }


    /**
     * DISCLAIMER: EU NÃO FIZ ISSO! NINGUÉM SABE QUEM FEZ!
     * QUEM SOUBER MORRE. NÃO FAÇAM ISSO EM CASA!!!
     *
     * WELCOME TO THE JUNGLE!!!
     */
//    public void convertoToIDF(){
//        ArrayList<Token> list_idf = new ArrayList<Token>();
//
//        /* Procura as funções no código */
//        for(int i = 0; i < size()-2; i++){
//            if(get(i).getTokenClass() == TokenClass.KEYWORD_FUNCAO){
//                TokenClass c = get(i+1).getTokenClass();
//                if(   c == TokenClass.IDENTIFIER
//                    || c == TokenClass.KEYWORD_VAZIO
//                    || c == TokenClass.KEYWORD_INTEIRO
//                    || c == TokenClass.KEYWORD_REAL
//                    || c == TokenClass.KEYWORD_CARACTERE
//                    || c == TokenClass.KEYWORD_STRING
//                    || c == TokenClass.KEYWORD_LOGICO)
//                    //&& c != TokenClass.Ke)
//                {
//                    /* Salva os identificadores (nomes das funções) em uma lista */
//                    if(get(i+2).getTokenClass() == TokenClass.IDENTIFIER){
//                        list_idf.add(get(i+2));
//                    }
//                }
//            }
//        }
//
//        /* Substitui as ocorrências de chamadas de função pelo ID_F */
//        for(int i = 0; i < size(); i++){
//            for(int j = 0; j < list_idf.size(); j++){
//                if(get(i).getLexeme().equals(list_idf.get(j).getLexeme())
//                       && !(get(i).getLine() == list_idf.get(j).getLine()
//                       && get(i).getPosition() == list_idf.get(j).getPosition())){
//                    get(i).setTokenClass(TokenClass.IDENTIFIER_F);
//                }
//            }
//        }
//    }
}
